using UnityEngine;
using System.Collections;
using DanielSig.UnityExtensions;
using DanielSig;
using System.Linq;

[RequireComponent(typeof(Radar))]
public class FOVSensor : MonoBehaviour, ISensor
{
	public bool HasFixedDirection{ get{ return false; } }
	public SensationType Type{ get{ return _type; } }
	public float[] Values{ get{ return _values; } }
	
	private SensationType _type;
	
	[SerializeField]
	private float[] _values = new float[2];
	
	private Radar _radar;
	private int _index = -1;
	
	public SensationType TargetType;
	public bool Remember;
	private Vector3 _memory;
	
	void Awake()
	{
		_radar = GetComponent<Radar>();
		FOVSensor[] others = this.GetComponents<FOVSensor>( c => c.TargetType == TargetType );
		_index = others.Max(c => c._index) + 1;
		
		if(IsEnemySensation)
			_values = new float[1];
		if(TargetType == SensationType.Enemy || TargetType == SensationType.Projectile)
			_values = new float[3];//third value is the direction the enemy/projectile is heading
	}
	
	public void UpdateSensors()
	{
		if(!transform) return;
		
		int counter = 0;
		Radar.Detection temp = _radar.VisibleObjects.FirstOrDefault
		(
			r =>
			{
				if(r.Type == SensationType.Enemy)
				{
					if(IsEnemySensation)
					{
						if(counter++ > 0)
							return true;
					}
				}
				if(r.Type == TargetType)
				{
					if(TargetType == SensationType.Enemy && r.Target == transform.parent)
						return false;
					
					if(counter++ >= _index)
						return true;
				}
				return false;
			}
		);
		if(temp != null && temp.Target)
		{
			if(IsEnemySensation)
			{
				_values[0] = TargetType == SensationType.EnemyHealth
					? temp.Target.GetComponent<HealthSensor>().Health
					: temp.Target.GetComponentInChildren<Gun>().AmmoCount;
				_type = TargetType;
			}
			else if(_values != null && _values.Length > 2)
			{
				_memory = temp.ClosestPoint;
				SetValues(_memory, temp.Distance, TargetType);
				if(TargetType == SensationType.Enemy)
					_values[2] = 1-(Quaternion.FromToRotation(transform.position.DirectionTowards(temp.Target.position), ((temp.Target.collider as CharacterController).velocity.normalized)).eulerAngles.y / 180);
				if(TargetType == SensationType.Projectile)
					_values[2] = 1-(Quaternion.FromToRotation(transform.position.DirectionTowards(temp.Target.position), temp.Target.forward).eulerAngles.y / 180);
			}
		}
		else if(Remember)
		{
			if(!IsEnemySensation)
				SetValues(_memory, _memory.DistanceTo(transform.position), _type);
		}
		else
		{
			_type = SensationType.None;
			_values[0] = 0F;
			if(_values.Length > 1) _values[1] = 0F;
		}
	}
	private void SetValues(Vector3 pos, float dist, SensationType type)
	{
		Vector3 dir = (pos - transform.position).normalized;
		float x = transform.right.Dot(dir);
		float z = transform.forward.Dot(dir);
		_type = type;
		_values[0] = dist;
		_values[1] = (Mathf.Acos(z) / Mathf.PI) * x.Sign();
	}
	void OnDrawGizmosSelected()
	{
		if(_type == TargetType)
		{
			if(_values.Length > 1 && _values[0] == _values[0] && _values[1] == _values[1])
			{
				Gizmos.color = Color.red;
				Gizmos.DrawLine(transform.position, transform.position + transform.forward.RotateY(_values[1] * 180F) * _values[0]);
			}
		}
	}
	private bool IsEnemySensation
	{
		get{ return TargetType == SensationType.EnemyAmmo || TargetType == SensationType.EnemyHealth; }
	}
}

